﻿using System;
using System.Collections.Generic;
using System.Linq;
using NHibernate;
using NHibernate.Linq;
using NHibernate.Criterion;
using Ornament.NHibernates;

namespace Ornament.MemberShip.Dao.NHibernateImple
{
    public sealed class UserDao : DaoBase<Guid, User>, IUserDao
    {
        public UserDao()
        {

        }

        public UserDao(bool useGlobalConnection)
            : base(useGlobalConnection)
        {

        }
        private IProjection _loginidProperty;
        private IProjection LoginProperty
        {
            get { return _loginidProperty ?? (_loginidProperty = Projections.Property<User>(s => s.LoginId)); }
        }
        protected override Order[] DefaultOrder
        {
            get { return new[] { Order.Asc(LoginProperty) }; }
        }

        #region IUserDao Members
        public IQueryable<User> Users
        {
            get { return SessionManager.Instance.CurrentSession.Query<User>(); }
        }
        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="loginIds">登录Id</param>
        /// <returns>用户对象集合</returns>
        public IList<User> GetUsers(string[] loginIds)
        {
            ICriterion c = Restrictions.In("LoginId", loginIds);
            return CreateCriteria().Add(c).List<User>();
        }
        /// <summary>
        /// 根据角色Id获取用户
        /// </summary>
        /// <param name="roleId">角色Id</param>
        /// <returns></returns>
        public IList<User> GetUsersInRole(string roleId)
        {
            return CreateCriteria().CreateCriteria("Roles").Add(Restrictions.Eq("Name", roleId)).List<User>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roleName"></param>
        /// <param name="loginMatch">模糊查询 支持 %</param>
        /// <returns></returns>
        public IList<User> FindUsersInRole(string roleName, string loginMatch)
        {
            return CreateCriteria()
                .Add(Restrictions.InsensitiveLike("LoginId", loginMatch))
                .CreateCriteria("Roles")
                .Add(Restrictions.Eq("Name", roleName))
                .List<User>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public User GetUserByEmail(string email)
        {
            return CreateCriteria().Add(Restrictions.Eq("Information.Email", email)).UniqueResult<User>();
        }

        /// <summary>
        /// 获取在某日期之后处于活动状态的用户
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public int GetActivityDateNumber(DateTime time)
        {
            return Count(Restrictions.Le("LastActivityDate", time));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="matchLoginId"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IList<User> FindUsersByLoginId(string matchLoginId, int pageIndex, int pageSize)
        {
            ICriteria ica = CreateCriteria();
            if (!String.IsNullOrEmpty(matchLoginId))
            {
                ica.Add(Restrictions.InsensitiveLike("LoginId", matchLoginId + "%"));
            }

            return Find(pageIndex, pageSize, ica);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="emailToMatch"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IList<User> FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize)
        {
            ICriteria ica = CreateCriteria().Add(Restrictions.InsensitiveLike("Email", emailToMatch));
            return Find(pageIndex, pageSize, ica);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="loginId"></param>
        /// <param name="email"></param>
        /// <param name="phone"></param>
        /// <param name="islockout"></param>
        /// <param name="isApproved"></param>
        /// <param name="startRow"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IList<User> Search(string loginId, string email, string phone, bool islockout, bool isApproved,
                                  int startRow, int pageSize)
        {
            ICriterion tion = CreateSearchCondition(loginId, email, phone, islockout, isApproved);

            ICriteria ica = CreateCriteria();
            ica.Add(tion);
            ica.SetMaxResults(pageSize);
            ica.SetFirstResult(startRow);
            return ica.List<User>();
        }

        public IList<User> Search(string searchProperty, string searchValue, bool isSortAsc, string sortProperty,
                                  int pageIndex, int pageSize, out int total)
        {
            SimpleExpression creator = Restrictions.Eq(searchProperty, searchValue);
            total = Count(creator);
            if (!String.IsNullOrEmpty(sortProperty))
                sortProperty = "LoginId";
            var order = new Order(sortProperty, isSortAsc);
            return
                CreateCriteria().Add(creator).AddOrder(order).SetFirstResult(pageIndex * pageSize).SetMaxResults(pageSize)
                    .List<User>();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="loginId"></param>
        /// <param name="email"></param>
        /// <param name="phone"></param>
        /// <param name="islockout"></param>
        /// <param name="isApproved"></param>
        /// <returns></returns>
        public int Count(string loginId, string email, string phone, bool islockout, bool isApproved)
        {
            ICriterion tion = CreateSearchCondition(loginId, email, phone, islockout, isApproved);

            ICriteria ica = CreateCriteria();
            ica.Add(tion);
            ica.SetProjection(Projections.Count("LoginId"));
            return ica.UniqueResult<int>();
        }


        public User Get(string loginId)
        {
            ICriteria cr = CreateCriteria().Add(Restrictions.Eq("LoginId", loginId));
            return cr.UniqueResult<User>();
        }


        public IList<User> GetUsers(UserGroup userGroup)
        {
            return CreateCriteria()
                .CreateCriteria("UserGroups")
                .Add(Restrictions.Eq("Id", userGroup.Id)).List<User>();
        }



        #endregion

        private int Count(SimpleExpression countCondition)
        {
            return CreateCriteria().Add(countCondition).SetProjection(Projections.Count("Id")).UniqueResult<Int32>();
        }

        private ICriterion CreateSearchCondition(string loginId,
                                                 string email,
                                                 string phone, bool islockout,
                                                 bool isApproved)
        {
            ICriterion tion = Restrictions.Eq("Information.IsLockout", islockout);
            tion = Restrictions.Or(tion, Restrictions.Eq("Information.IsApproved", isApproved));


            if (!String.IsNullOrEmpty(loginId))
                tion = Restrictions.And(tion, Restrictions.InsensitiveLike("LoginId", loginId));
            if (!String.IsNullOrEmpty(phone))
                tion = Restrictions.And(tion, Restrictions.InsensitiveLike("Phone", phone));
            if (!String.IsNullOrEmpty(email))
                tion = Restrictions.And(tion, Restrictions.InsensitiveLike("Email", email));
            return tion;
        }
    }
}